
package motorprediccion;

import java.sql.*;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;

/**
 *
 * @author dani
 */
public class DataLoader {
    Connection conexionBD;

    public DataLoader() {
          conexionBD = null;

          try {
            // The second and third arguments are the username and password,
            // respectively. They should be whatever is necessary to connect
            // to the database.
            conexionBD = DriverManager.getConnection("jdbc:postgresql://localhost/sistemaprediccion",
                                            "postgres", "postgres");
          }
          catch (SQLException se) {
            System.out.println("Couldn't connect: print out a stack trace and exit.");
            se.printStackTrace();
            System.exit(1);
          }

          if (conexionBD != null)
            System.out.println("Conexion exitosa con la BD");
          else
            System.out.println("No se pudo conectar a la BD");

    }

    public ArrayList<Recorrido> cargarRecorridos() throws SQLException {
        Statement s;
        String consultaParadas, consultaLineas = "SELECT idrecorrido, linea, frecuencia, empresa_id FROM recorrido;";
        ResultSet resultadoParadas, resultadoLineas;
        ArrayList<Recorrido> recorridos = new ArrayList<Recorrido>(0);
        //carga todas las lineas en una sola
        
        try {
            s = conexionBD.createStatement();
            resultadoLineas = s.executeQuery(consultaLineas);
            while(resultadoLineas.next()){ // corregir carga de recorridos
                recorridos.add(new Recorrido(resultadoLineas.getInt("idrecorrido"),resultadoLineas.getString("linea")));
            }
            for (int i=0; i<recorridos.size(); i++){
                consultaParadas = "SELECT idparada, linea_id, calle1, calle2, proximaparada, latitud, longitud, orden"+
                " FROM parada WHERE linea_id = "+ recorridos.get(i).getId() +" order by orden;";
                resultadoParadas = s.executeQuery(consultaParadas);
                while(resultadoParadas.next()) {
                    Double lat = resultadoParadas.getDouble("latitud");
                    Double lon = resultadoParadas.getDouble("longitud");
                    recorridos.get(i).agregarParada(new Parada(resultadoParadas.getInt("idparada"), resultadoParadas.getInt("orden"), lat, lon));
                }
            }
            
        }
        catch (SQLException se) {
          System.out.println("SQL Error");
          se.printStackTrace();
          System.exit(1);
        }
        return recorridos;
    }

    public ArrayList<DatoPosicional> obtenerDatosPosicionales() throws SQLException {
        Statement s;
        ResultSet resultado;
        ArrayList<DatoPosicional> nuevosDatos = new ArrayList<DatoPosicional>(0);
        try {
            s = conexionBD.createStatement();
            String consulta = "SELECT \"vehicleId\", latitud, longitud, "+
            "\"fechaConsulta\"+\"secsSinceLastReport\"*1000 as fecha "+
            "FROM motorprediccion.posiciones_crudo "+
            //"where predictable = 'true' order by fecha asc;";
            "where predictable = 'true' and extract(DAY from to_timestamp(\"fechaConsulta\"/1000)) = 27 order by fecha asc;";
            //"where predictable = 'true' and \"vehicleId\"= 5609 order by fecha asc;";
            //"where predictable = 'true' and extract(HOUR from to_timestamp(\"fechaConsulta\")) between 15 and 17 order by fecha asc;";
            //\"vehicleId\" = 5620 and 
            resultado = s.executeQuery(consulta);

            while(resultado.next()) {
                Float lat = resultado.getFloat("latitud");
                Float lon = resultado.getFloat("longitud");
                GregorianCalendar fecha = new GregorianCalendar();
                fecha.setTimeInMillis(resultado.getLong("fecha"));
                nuevosDatos.add(new DatoPosicional(resultado.getInt("vehicleId"), lat,lon, fecha));
               }
            }
        catch (SQLException se) {
          System.out.println("SQL Error");
          se.printStackTrace();
          System.exit(1);
        }
        return nuevosDatos;
    }

    public void guardarDatosProcesados(ArrayList<DatoProcesado> datos) {
        try {
            Statement s = this.conexionBD.createStatement();
            for(int i=0 ; i < datos.size(); i++) {
                 String consulta = "INSERT INTO motorprediccion.datosprocesados("+
                    "idcolectivo, idparada, tiempo, fecha) values ("+
                    datos.get(i).getIdcolectivo()+", "+
                    datos.get(i).getParada().getId()+", "+
                    datos.get(i).getTiempoSegundos()+", "+
                    "to_timestamp("+datos.get(i).getHoraArribo().getTimeInMillis()/1000+"));";

                if(consulta.length()>0) { //comparacion invalida, siempre sera mayor que 0, ver con los datos
                    s.executeUpdate(consulta);
                }
            }
        }
        catch (SQLException se) {
          System.out.println("Error en la BD");
          se.printStackTrace();
          System.exit(1);
        }
    }

    public HashMap cargarPromedios() throws SQLException {
        String consulta = "SELECT idparada, promedio, desstd, orden FROM motorprediccion.promedios order by orden asc;";
        ResultSet resultado;
        HashMap promedios = new HashMap();

        try {
            Statement s = conexionBD.createStatement();
            resultado = s.executeQuery(consulta);
            while(resultado.next()) {
                promedios.put(resultado.getInt("orden"), resultado.getDouble("promedio"));
            }
        }
        catch (SQLException se) {
          System.out.println("SQL Error");
          se.printStackTrace();
          System.exit(1);
        }
        return promedios;
    }

    public HashMap cargarDesv() throws SQLException {
        String consulta = "SELECT idparada, promedio, desstd, orden FROM motorprediccion.promedios order by orden asc;";
        ResultSet resultado;
        HashMap desviaciones = new HashMap();

        try {
            Statement s = conexionBD.createStatement();
            resultado = s.executeQuery(consulta);
            while(resultado.next()) {
                desviaciones.put(resultado.getInt("orden"), resultado.getDouble("desstd"));
            }
        }
        catch (SQLException se) {
          System.out.println("SQL Error");
          se.printStackTrace();
          System.exit(1);
        }
        return desviaciones;
    }

    public void guardarPrediccion(int idColectivo, int origen, int destino, GregorianCalendar horaEstimacion, GregorianCalendar arriboEstimado) {
        Statement s = null;

        try {
            s = this.conexionBD.createStatement();
            String consulta= "INSERT INTO motorprediccion.predicciones("+
                "idcolectivo, paradaorigen, paradadestino, paradasdistancia, "+
                " horaestimacion, arriboestimado) VALUES ("+
                idColectivo + ", "+
                origen + ", "+
                destino + ", "+
                (destino-origen)+", "+
                "to_timestamp("+horaEstimacion.getTimeInMillis()/1000+"),"+
                "to_timestamp("+arriboEstimado.getTimeInMillis()/1000+"));";
            if(consulta.length()>0) {
                s.executeUpdate(consulta);
            }
        }
        catch (SQLException se) {
          System.out.println("SQL Error");
          se.printStackTrace();
          System.exit(1);
        }
    }
    
    public void guardarPrediccionNormal(int idColectivo, int origen, int destino, GregorianCalendar horaEstimacion, GregorianCalendar arriboEstimado) {
        Statement s = null;

        try {
            s = this.conexionBD.createStatement();
            String consulta= "INSERT INTO motorprediccion.prediccionesdistnormal("+
                "idcolectivo, paradaorigen, paradadestino, paradasdistancia, "+
                " horaestimacion, arriboestimado) VALUES ("+
                idColectivo + ", "+
                origen + ", "+
                destino + ", "+
                (destino-origen)+", "+
                "to_timestamp("+horaEstimacion.getTimeInMillis()/1000+"),"+
                "to_timestamp("+arriboEstimado.getTimeInMillis()/1000+"));";
            if(consulta.length()>0) {
                s.executeUpdate(consulta);
            }
        }
        catch (SQLException se) {
          System.out.println("Error en la BD");
          se.printStackTrace();
          System.exit(1);
        }
    }
}
